package lol.clann.bukkit.pluginboot.util;

import lol.clann.clannboot.annotation.inject.Inject;
import lol.clann.clannboot.annotation.svc.PostInstance;
import lol.clann.clannboot.annotation.svc.Service;
import lol.clann.clannboot.util.clazz.ClassUtils;
import lol.clann.clannboot.util.clazz.WrapClass;
import org.bukkit.World;
import org.nutz.lang.Lang;

import java.lang.reflect.Constructor;
import java.util.Collection;

/**
 * @author pyz
 * @date 2018/10/6 下午4:17
 */
@Service(priority = Integer.MAX_VALUE)
public class PacketUtils {

    public static final WrapClass classPacketPlayOutBlockChange = ClassUtils.forName("{nms}.PacketPlayOutBlockChange");
    public static final WrapClass classPacketPlayOutHeldItemSlot = ClassUtils.forName("{nms}.PacketPlayOutHeldItemSlot");
    public static final WrapClass classPacketPlayOutChat = ClassUtils.forName("{nms}.PacketPlayOutChat");
    private Constructor constructorPacketPlayOutBlockChange;
    private Constructor constructorPacketPlayOutHeldItemSlot;

    @Inject
    private WorldUtils worldUtils;

    public Object newPacketPlayOutBlockChange(int x, int y, int z, World world) {
        return newInstance(constructorPacketPlayOutBlockChange, x, y, z, worldUtils.toNMS(world));
    }

    public Object newPacketPlayOutHeldItemSlot(int hotbar) {
        return newInstance(constructorPacketPlayOutHeldItemSlot, hotbar);
    }

    private Object newInstance(Constructor constructor, Object... params) {
        try {
            return constructor.newInstance(params);
        } catch (Exception e) {
            throw Lang.wrapThrow(e);
        }
    }

    @PostInstance
    private void init() {
        constructorPacketPlayOutBlockChange = findConstructor(classPacketPlayOutBlockChange);
        constructorPacketPlayOutHeldItemSlot = findConstructor(classPacketPlayOutHeldItemSlot);
    }

    private Constructor findConstructor(WrapClass wrapClass) {
        Collection<Constructor> cs = wrapClass.getAllConstructors();
        for (Constructor c : cs) {
            if (c.getParameters().length > 0) {
                return c;
            }
        }
        throw new RuntimeException("没有找到有参构造函数:" + wrapClass.getName());
    }
}
